"""
安全工具类
提供密码加密、输入验证、SQL注入防护等功能
"""
import re
import bcrypt
from flask import request, jsonify
from functools import wraps

def hash_password(password):
    """
    使用bcrypt加密密码
    
    Args:
        password: 明文密码
    
    Returns:
        str: 加密后的密码
    """
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def check_password(password, hashed):
    """
    验证密码
    
    Args:
        password: 明文密码
        hashed: 加密后的密码
    
    Returns:
        bool: 密码是否正确
    """
    return bcrypt.checkpw(password.encode('utf-8'), hashed.encode('utf-8'))

def validate_input(data, rules):
    """
    验证输入数据
    
    Args:
        data: 要验证的数据字典
        rules: 验证规则字典
    
    Returns:
        tuple: (is_valid, error_message)
    
    Example:
        rules = {
            'username': {
                'required': True,
                'type': str,
                'min_length': 3,
                'max_length': 20,
                'pattern': r'^[a-zA-Z0-9_]+$'
            },
            'email': {
                'required': True,
                'type': str,
                'pattern': r'^[^@]+@[^@]+\\.[^@]+$'  # 使用双反斜杠避免警告
            }
        }
    """
    for field, rule in rules.items():
        value = data.get(field)
        
        # 必填验证
        if rule.get('required') and not value:
            return False, f'{field}是必填项'
        
        if not value:
            continue
        
        # 类型验证
        if 'type' in rule and not isinstance(value, rule['type']):
            return False, f'{field}类型错误'
        
        # 长度验证
        if isinstance(value, str):
            if 'min_length' in rule and len(value) < rule['min_length']:
                return False, f'{field}长度不能少于{rule["min_length"]}个字符'
            if 'max_length' in rule and len(value) > rule['max_length']:
                return False, f'{field}长度不能超过{rule["max_length"]}个字符'
        
        # 正则验证
        if 'pattern' in rule and not re.match(rule['pattern'], str(value)):
            return False, f'{field}格式不正确'
    
    return True, None

def sanitize_input(data):
    """
    清理输入数据，防止XSS攻击
    
    Args:
        data: 输入数据（可以是字符串或字典）
    
    Returns:
        清理后的数据
    """
    if isinstance(data, str):
        # 移除HTML标签
        data = re.sub(r'<[^>]+>', '', data)
        # 转义特殊字符
        data = data.replace('<', '&lt;').replace('>', '&gt;')
        data = data.replace('"', '&quot;').replace("'", '&#x27;')
        return data
    elif isinstance(data, dict):
        return {k: sanitize_input(v) for k, v in data.items()}
    elif isinstance(data, list):
        return [sanitize_input(item) for item in data]
    else:
        return data

def validate_json_input(rules):
    """
    装饰器：验证JSON输入
    
    Usage:
        @validate_json_input({
            'username': {'required': True, 'type': str, 'min_length': 3},
            'password': {'required': True, 'type': str, 'min_length': 6}
        })
        def register():
            data = request.get_json()
            # data已经经过验证和清理
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not request.is_json:
                return jsonify({
                    'status': 'error',
                    'message': '请求必须是JSON格式'
                }), 400
            
            data = request.get_json()
            if not data:
                return jsonify({
                    'status': 'error',
                    'message': '请求体不能为空'
                }), 400
            
            # 验证输入
            is_valid, error_message = validate_input(data, rules)
            if not is_valid:
                return jsonify({
                    'status': 'error',
                    'message': error_message
                }), 400
            
            # 清理输入
            data = sanitize_input(data)
            request.validated_data = data
            
            return f(*args, **kwargs)
        return decorated_function
    return decorator

def prevent_sql_injection(query):
    """
    防止SQL注入（用于原生SQL查询）
    
    Args:
        query: SQL查询字符串
    
    Returns:
        bool: 是否包含可疑的SQL注入模式
    """
    dangerous_patterns = [
        r"(\bOR\b|\bAND\b)\s+\d+\s*=\s*\d+",
        r"(\bUNION\b|\bSELECT\b|\bINSERT\b|\bUPDATE\b|\bDELETE\b|\bDROP\b)",
        r"(--|#|/\*|\*/)",  # 修复转义序列警告
        r"(\bEXEC\b|\bEXECUTE\b)",
        r"(\bSCRIPT\b)",
    ]
    
    query_upper = query.upper()
    for pattern in dangerous_patterns:
        if re.search(pattern, query_upper):
            return False
    
    return True

